package cn.birdbaby.plugins.sync.methodsyner.feign;

import cn.birdbaby.plugins.constants.Constants;
import cn.birdbaby.plugins.sync.methodsyner.AbstractMethodSyncer;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.Collection;
import java.util.List;

/**
 * @author llorando 13/8/24 4:54 pm
 */
public class FeignMethodSyncer extends AbstractMethodSyncer {
    /**
     * 寻找对应的feign类
     * @param psiClass
     * @return
     */
    @Override
    public PsiClass findClass(PsiClass psiClass) {
        //通常是在controller类上发起同步操作
        String name = psiClass.getName().replace(Constants.CONTROLLER_SUFFIX,"")+ getSuffix();
        //todo 但凡有同名的就凉凉
        return PsiShortNamesCache.getInstance(psiClass.getProject()).getClassesByName(name,GlobalSearchScope.allScope(psiClass.getProject()))[0];
    }

    @Override
    public void addPsiElement(PsiClass destination, List<PsiElement> psiElements) {
        PsiJavaToken rbrace = locateRBrace(destination);//最后一个，一定是右大括号
        for (PsiElement element : psiElements) {
            PsiElement copy=element.copy();

            //feign的接口不需要方法体
            PsiCodeBlock codeBlock= PsiTreeUtil.findChildOfType(copy,PsiCodeBlock.class);
            codeBlock.delete();

            //除了xxxMapping之外的注解，都不保留
            Collection<PsiAnnotation> annotations = PsiTreeUtil.findChildrenOfAnyType(copy, PsiAnnotation.class);
            for(PsiAnnotation annotation:annotations){
                String name=annotation.getNameReferenceElement().getReferenceName();
                if(!Constants.mappings.contains(name)){
                    annotation.delete();
                }
            }
            destination.addBefore(copy, rbrace);
        }
    }

    @Override
    public String getSuffix() {
        return Constants.FEIGN_SUFFIX;
    }

    //被xxxMapping注解标记的方法，才去复制
    public boolean skip(PsiElement method) {
        Collection<PsiAnnotation> psiAnnotations = PsiTreeUtil.findChildrenOfAnyType(method, PsiAnnotation.class);
        if (psiAnnotations.isEmpty()) return true;

        for (PsiAnnotation psiAnnotation : psiAnnotations) {
            String name = psiAnnotation.getNameReferenceElement().getReferenceName();
            if (Constants.mappings.contains(name)) {
                return false;
            }
        }
        return true;
    }

}
